<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>全国旅游景点数据分析大屏</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Microsoft YaHei", sans-serif;
        }

        body {
            background: linear-gradient(135deg, #0c2461, #1e3799, #4a69bd);
            color: #fff;
            min-height: 100vh;
            overflow-x: hidden;
        }

        .container {
            max-width: 1920px;
            margin: 0 auto;
            padding: 20px;
        }

        .header {
            text-align: center;
            padding: 20px 0;
            position: relative;
        }

        .header h1 {
            font-size: 48px;
            text-shadow: 0 0 10px rgba(79, 195, 247, 0.8);
            letter-spacing: 4px;
            margin-bottom: 10px;
            background: linear-gradient(to right, #4fc3f7, #29b6f6, #03a9f4);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            position: relative;
            display: inline-block;
        }

        .header h1::after {
            content: "";
            position: absolute;
            bottom: -10px;
            left: 50%;
            transform: translateX(-50%);
            width: 200px;
            height: 4px;
            background: linear-gradient(to right, #4fc3f7, #03a9f4);
            border-radius: 2px;
        }

        .stats-container {
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap;
            margin: 30px 0;
            gap: 20px;
        }

        .stat-card {
            background: rgba(16, 42, 88, 0.6);
            border-radius: 10px;
            padding: 25px;
            flex: 1;
            min-width: 250px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(79, 195, 247, 0.3);
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .stat-card:hover {
            transform: translateY(-5px);
            box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
            border-color: rgba(79, 195, 247, 0.6);
        }

        .stat-card::before {
            content: "";
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 4px;
            background: linear-gradient(to right, #4fc3f7, #03a9f4);
        }

        .stat-card h3 {
            font-size: 20px;
            margin-bottom: 15px;
            color: #4fc3f7;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .stat-card .value {
            font-size: 42px;
            font-weight: bold;
            text-align: center;
            margin: 15px 0;
            text-shadow: 0 0 10px rgba(79, 195, 247, 0.6);
            background: linear-gradient(to bottom, #fff, #b3e5fc);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .stat-card .desc {
            text-align: center;
            font-size: 16px;
            opacity: 0.8;
        }

        .charts-container {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 20px;
            margin-bottom: 30px;
        }

        .chart-box {
            background: rgba(16, 42, 88, 0.6);
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
            border: 1px solid rgba(79, 195, 247, 0.3);
            height: 450px;
            display: flex;
            flex-direction: column;
        }

        .chart-box h3 {
            font-size: 22px;
            margin-bottom: 20px;
            color: #4fc3f7;
            padding-bottom: 10px;
            border-bottom: 1px solid rgba(79, 195, 247, 0.3);
        }

        .chart-container {
            flex: 1;
            width: 100%;
        }

        .full-width {
            grid-column: 1 / -1;
        }

        .loading {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100%;
            font-size: 18px;
            color: #4fc3f7;
        }

        .loading::after {
            content: "";
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(79, 195, 247, 0.3);
            border-radius: 50%;
            border-top-color: #4fc3f7;
            animation: spin 1s linear infinite;
            margin-left: 10px;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        .footer {
            text-align: center;
            padding: 20px;
            font-size: 14px;
            color: rgba(255, 255, 255, 0.7);
            border-top: 1px solid rgba(255, 255, 255, 0.1);
            margin-top: 20px;
        }

        .glow {
            animation: glow 2s ease-in-out infinite alternate;
        }

        @keyframes glow {
            from {
                text-shadow: 0 0 5px #fff, 0 0 10px #4fc3f7, 0 0 15px #4fc3f7;
            }
            to {
                text-shadow: 0 0 10px #fff, 0 0 20px #4fc3f7, 0 0 30px #4fc3f7;
            }
        }

        @media (max-width: 1200px) {
            .charts-container {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1 class="glow">全国旅游景点数据分析大屏</h1>
            <p>实时监控全国景点数据动态，助力旅游行业决策</p>
        </div>

        <div class="stats-container">
            <div class="stat-card">
                <h3>总景点数量</h3>
                <div class="value" id="total-attractions">0</div>
                <div class="desc">全国景点总量统计</div>
            </div>

            <div class="stat-card">
                <h3>景点总销量</h3>
                <div class="value" id="total-sales">0</div>
                <div class="desc">全国景点门票总销量</div>
            </div>

            <div class="stat-card">
                <h3>平均评分</h3>
                <div class="value" id="avg-rating">0.0</div>
                <div class="desc">全国景点平均评分</div>
            </div>

            <div class="stat-card">
                <h3>平均价格</h3>
                <div class="value" id="avg-price">¥0.0</div>
                <div class="desc">全国景点门票平均价格</div>
            </div>
        </div>

        <div class="charts-container">
            <div class="chart-box">
                <h3>门票价格分布</h3>
                <div class="chart-container" id="price-chart">
                    <div class="loading">数据加载中...</div>
                </div>
            </div>

            <div class="chart-box">
                <h3>热门景点销量TOP20</h3>
                <div class="chart-container" id="sales-chart">
                    <div class="loading">数据加载中...</div>
                </div>
            </div>

            <div class="chart-box">
                <h3>各省高等级景区分布</h3>
                <div class="chart-container" id="province-chart">
                    <div class="loading">数据加载中...</div>
                </div>
            </div>

            <div class="chart-box">
                <h3>4A-5A景区数量散点图</h3>
                <div class="chart-container" id="scatter-chart">
                    <div class="loading">数据加载中...</div>
                </div>
            </div>
        </div>

        <div class="footer">
            <p> 全国旅游景点数据分析平台</p>
        </div>
    </div>

    <script>
        // 初始化ECharts实例
        const priceChart = echarts.init(document.getElementById('price-chart'));
        const salesChart = echarts.init(document.getElementById('sales-chart'));
        const provinceChart = echarts.init(document.getElementById('province-chart'));
        const scatterChart = echarts.init(document.getElementById('scatter-chart'));


        // 获取平均价格
        async function fetchAvgPrice() {
            try {
                const response = await axios.get('/menu/avg_price_data');
                const avgPrice = response.data.avg_price;
                document.getElementById('avg-price').textContent = `¥${avgPrice.toFixed(2)}`;
            } catch (error) {
                console.error('获取平均价格失败:', error);
            }
        }

        // 获取平均评分
        async function fetchAvgRating() {
            try {
                const response = await axios.get('/menu/avg_rating_data');
                const avgRating = response.data.avg_rating;
                document.getElementById('avg-rating').textContent = avgRating.toFixed(2);
            } catch (error) {
                console.error('获取平均评分失败:', error);
            }
        }

        // 获取价格分布数据
        async function fetchPriceDistribution() {
            try {
                const response = await axios.get('/menu/get_price_distribution');
                if (response.data.code === 0) {
                    const data = response.data.data;
                    const ranges = data.ranges;
                    const counts = data.counts;

                    document.getElementById('total-attractions').textContent = data.total;

                    const chartData = ranges.map((range, index) => ({
                        name: range,
                        value: counts[index]
                    }));

                    priceChart.setOption({
                        tooltip: {
                            trigger: 'item',
                            formatter: '{a} <br/>{b}: {c} ({d}%)'
                        },
                        legend: {
                            orient: 'vertical',
                            right: 10,
                            top: 'center',
                            data: ranges,
                            textStyle: {
                                color: '#fff'
                            }
                        },
                        series: [
                            {
                                name: '价格分布',
                                type: 'pie',
                                radius: ['40%', '70%'],
                                center: ['40%', '50%'],
                                avoidLabelOverlap: false,
                                itemStyle: {
                                    borderRadius: 10,
                                    borderColor: '#0c2461',
                                    borderWidth: 2
                                },
                                label: {
                                    show: false,
                                    position: 'center'
                                },
                                emphasis: {
                                    label: {
                                        show: true,
                                        fontSize: '18',
                                        fontWeight: 'bold',
                                        formatter: '{b}\n{c} ({d}%)'
                                    }
                                },
                                labelLine: {
                                    show: false
                                },
                                data: chartData
                            }
                        ],
                        color: ['#4fc3f7', '#29b6f6', '#03a9f4', '#0288d1', '#0277bd', '#01579b', '#014377', '#012f55']
                    });
                }
            } catch (error) {
                console.error('获取价格分布失败:', error);
            }
        }

        // 获取热门景点销量数据
        async function fetchHotSales() {
            try {
                const response = await axios.get('/menu/hot_sales_attractions');
                const attractions = response.data.attractions;
                const sales = response.data.sales;

                // 更新总销量
                const totalSales = sales.reduce((sum, val) => sum + val, 0);
                document.getElementById('total-sales').textContent = totalSales.toLocaleString();

                salesChart.setOption({
                    tooltip: {
                        trigger: 'axis',
                        axisPointer: {
                            type: 'shadow'
                        }
                    },
                    grid: {
                        left: '3%',
                        right: '4%',
                        bottom: '3%',
                        top: '10%',
                        containLabel: true
                    },
                    xAxis: {
                        type: 'value',
                        axisLabel: {
                            color: '#fff'
                        },
                        splitLine: {
                            lineStyle: {
                                color: 'rgba(255, 255, 255, 0.1)'
                            }
                        }
                    },
                    yAxis: {
                        type: 'category',
                        data: attractions,
                        axisLabel: {
                            color: '#fff',
                            interval: 0,
                            fontSize: 12
                        }
                    },
                    series: [
                        {
                            name: '销量',
                            type: 'bar',
                            data: sales,
                            itemStyle: {
                                color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
                                    { offset: 0, color: '#4fc3f7' },
                                    { offset: 1, color: '#01579b' }
                                ])
                            },
                            label: {
                                show: true,
                                position: 'right',
                                color: '#fff'
                            }
                        }
                    ]
                });
            } catch (error) {
                console.error('获取热门景点销量失败:', error);
            }
        }

        // 获取各省高等级景区数据
        async function fetchProvinceData() {
            try {
                const response = await axios.get('/menu/get_rose_data');
                if (response.data.code === 0) {
                    const data = response.data.data;

                    provinceChart.setOption({
                        tooltip: {
                            trigger: 'item',
                            formatter: '{a} <br/>{b}: {c}'
                        },
                        legend: {
                            type: 'scroll',
                            orient: 'vertical',
                            right: 10,
                            top: 20,
                            bottom: 20,
                            textStyle: {
                                color: '#fff'
                            }
                        },
                        series: [
                            {
                                name: '高等级景区',
                                type: 'pie',
                                radius: ['20%', '90%'],
                                center: ['40%', '50%'],
                                roseType: 'area',
                                itemStyle: {
                                    borderRadius: 8
                                },
                                data: data
                            }
                        ],
                        color: ['#4fc3f7', '#29b6f6', '#03a9f4', '#0288d1', '#0277bd',
                                '#01579b', '#014377', '#012f55', '#4fc3f7', '#29b6f6',
                                '#03a9f4', '#0288d1', '#0277bd', '#01579b', '#014377']
                    });
                }
            } catch (error) {
                console.error('获取省份数据失败:', error);
            }
        }

        // 获取散点数据
        async function fetchScatterData() {
            try {
                const response = await axios.get('/menu/high_grade_attractions');
                const provinces = response.data.provinces;
                const counts = response.data.counts;

                // 准备散点图数据
                const scatterData = provinces.map((province, index) => ({
                    name: province,
                    value: [index, counts[index], counts[index]] // [x, y, size]
                }));

                scatterChart.setOption({
                    tooltip: {
                        trigger: 'item',
                        formatter: function(params) {
                            return `${params.name}<br/>4A-5A景区数量: ${params.value[2]}`;
                        }
                    },
                    grid: {
                        left: '3%',
                        right: '7%',
                        bottom: '10%',
                        top: '10%',
                        containLabel: true
                    },
                    xAxis: {
                        type: 'category',
                        data: provinces,
                        axisLabel: {
                            color: '#fff',
                            interval: 0,
                            rotate: 45
                        },
                        axisLine: {
                            lineStyle: {
                                color: 'rgba(255, 255, 255, 0.3)'
                            }
                        },
                        splitLine: {
                            show: true,
                            lineStyle: {
                                color: 'rgba(255, 255, 255, 0.1)'
                            }
                        }
                    },
                    yAxis: {
                        type: 'value',
                        name: '景区数量',
                        nameTextStyle: {
                            color: '#fff'
                        },
                        axisLabel: {
                            color: '#fff'
                        },
                        axisLine: {
                            lineStyle: {
                                color: 'rgba(255, 255, 255, 0.3)'
                            }
                        },
                        splitLine: {
                            lineStyle: {
                                color: 'rgba(255, 255, 255, 0.1)'
                            }
                        }
                    },
                    series: [{
                        type: 'scatter',
                        symbolSize: function(data) {
                            return Math.min(30 + data[2] * 0.5, 60); // 根据数量调整点的大小
                        },
                        itemStyle: {
                            color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{
                                offset: 0,
                                color: 'rgba(79, 195, 247, 0.8)'
                            }, {
                                offset: 1,
                                color: 'rgba(1, 87, 155, 0.8)'
                            }])
                        },
                        emphasis: {
                            itemStyle: {
                                color: '#4fc3f7',
                                shadowBlur: 10,
                                shadowColor: 'rgba(79, 195, 247, 0.5)'
                            }
                        },
                        data: scatterData
                    }]
                });
            } catch (error) {
                console.error('获取散点图数据失败:', error);
                document.getElementById('scatter-chart').innerHTML =
                    '<div style="color:#ff6b6b;text-align:center;padding:20px">散点图数据加载失败</div>';
            }
        }

        // 获取所有数据
        async function fetchAllData() {
            await fetchAvgPrice();
            await fetchAvgRating();
            await fetchPriceDistribution();
            await fetchHotSales();
            await fetchProvinceData();
            await fetchScatterData();
        }

        // 初始化页面
        fetchAllData();

        // 每5分钟刷新一次数据
        setInterval(fetchAllData, 300000);

        // 窗口大小变化时调整图表
        window.addEventListener('resize', function() {
            priceChart.resize();
            salesChart.resize();
            provinceChart.resize();
            scatterChart.resize();
        });
    </script>
</body>
</html>